package com.ly.heart.service.impl;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.KingAllocateDetailEntity;
import com.ly.heart.domain.KingRealInventoryEntity;
import com.ly.heart.domain.dto.KingApplyAllocateDto;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.heart.domain.vo.KingApplyAllocateVo;
import com.ly.heart.service.IActModelService;
import com.ly.heart.service.IKingAllocateDetailService;
import com.ly.heart.service.IKingRealInventoryService;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import org.springframework.stereotype.Service;
import com.ly.heart.mapper.KingApplyAllocateMapper;
import com.ly.heart.domain.KingApplyAllocateEntity;
import com.ly.heart.service.IKingApplyAllocateService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 调拨申请单Service业务层处理
 *
 * @author wutao
 * @date 2024-08-12
 */
@Service
public class KingApplyAllocateServiceImpl extends ServiceImpl<KingApplyAllocateMapper, KingApplyAllocateEntity> implements IKingApplyAllocateService {
    @Resource
    private KingApplyAllocateMapper kingApplyAllocateMapper;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    private IKingAllocateDetailService kingAllocateDetailService;
    @Resource
    private IKingRealInventoryService kingRealInventoryEntityService;
    @Resource
    private IActModelService actModelService;

    /**
     * 查询调拨申请单
     *
     * @param id 调拨申请单ID
     * @return 调拨申请单
     */
    @Override
    public KingApplyAllocateEntity selectKingApplyAllocateById(String id) {
        KingApplyAllocateEntity allocateEntity = this.getById(id);
        List<KingAllocateDetailEntity> list = kingAllocateDetailService.list(new LambdaQueryWrapper<KingAllocateDetailEntity>().eq(KingAllocateDetailEntity::getAllocateId, id));
        allocateEntity.setKingAllocateDetailEntityList(list);
        return allocateEntity;
    }

    /**
     * 查询调拨申请单列表
     *
     * @param kingApplyAllocate 调拨申请单
     * @return 调拨申请单
     */
    @Override
    public List<KingApplyAllocateEntity> selectKingApplyAllocateList(KingApplyAllocateEntity kingApplyAllocate) {
        return kingApplyAllocateMapper.selectKingApplyAllocateList(kingApplyAllocate);
    }

    /**
     * 新增调拨申请单
     * todo:要检验调拨的商品库存是否充足
     *
     * @param kingApplyAllocate 调拨申请单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult draft(KingApplyAllocateEntity kingApplyAllocate) {
        if (CollectionUtils.isEmpty(kingApplyAllocate.getKingAllocateDetailEntityList())) {
            return AjaxResult.error("请选择明细");
        }
        Date nowDate = DateUtils.getNowDate();
        String userId = SecurityUtils.getLoginUser().getUser().getUserId();
        String id = SnowflakeIdWorker.getInstance().nextStringId();
        kingApplyAllocate.setId(id);
        String companyId = CurrentUserUtil.getCompanyId();
        SysDept sysDept = sysDeptService.getById(companyId);
        int count = this.count();
        String countStr = String.format("%06d", count);
        String firstLetter = ChineseToPinyin.getFirstLetter(sysDept.getDeptName());
        String docNum = firstLetter.concat("_DBSQD_").concat(countStr);
        kingApplyAllocate.setDocNum(docNum);
        kingApplyAllocate.setState(ConstUtil.STATE_IN_DRAFT);
        kingApplyAllocate.setCreateTime(nowDate);
        kingApplyAllocate.setCreateBy(userId);
        checkKingRealInventory(kingApplyAllocate.getKingAllocateDetailEntityList());
        kingApplyAllocate.getKingAllocateDetailEntityList().forEach(kingAllocateDetailEntity -> {
            kingAllocateDetailEntity.setId(SnowflakeIdWorker.getInstance().nextStringId());
            kingAllocateDetailEntity.setAllocateId(id);
            kingAllocateDetailEntity.setBusinessType(ConstUtil.ALLOCATE_DETAIL_APPLY_TYPE_STR);
            kingAllocateDetailEntity.setCreateTime(nowDate);
            kingAllocateDetailEntity.setCreateBy(userId);
        });
        boolean b = kingAllocateDetailService.saveBatch(kingApplyAllocate.getKingAllocateDetailEntityList());
        if (!b) {
            return AjaxResult.error("新增失败");
        }
        boolean save = this.save(kingApplyAllocate);
        if (!save) {
            return AjaxResult.error("新增失败");
        }
        return AjaxResult.success("暂存调拨申请单成功", id);
    }

    /**
     * 提交调拨申请单
     * @param kingApplyAllocate
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submit(KingApplyAllocateEntity kingApplyAllocate) {
        StartProcessDto startDto = new StartProcessDto().
                setBusinessId(kingApplyAllocate.getId()).
                setBusinessType(kingApplyAllocate.getBusinessType()).setModelId(kingApplyAllocate.getModelId()).
                setBusinessName("调拨申请单".concat(kingApplyAllocate.getId()));
        String instanceId = actModelService.startProcess(startDto);
        kingApplyAllocate.setInstanceId(instanceId);
        kingApplyAllocate.setState(ConstUtil.STATE_IN_PROCESS);
        boolean updated = this.updateById(kingApplyAllocate);
        if (!updated) {
            return AjaxResult.error("提交失败");
        }
        return AjaxResult.success("提交调拨申请单成功");
    }

    /**
     * 修改调拨申请单
     *
     * @param kingApplyAllocate 调拨申请单
     * @return 结果
     */
    @Override
    public int updateKingApplyAllocate(KingApplyAllocateEntity kingApplyAllocate) {
        kingApplyAllocate.setUpdateTime(DateUtils.getNowDate());
        return kingApplyAllocateMapper.updateKingApplyAllocate(kingApplyAllocate);
    }

    /**
     * 批量删除调拨申请单
     *
     * @param ids 需要删除的调拨申请单ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteKingApplyAllocateByIds(String[] ids) {
        boolean removed = this.removeByIds(Arrays.asList(ids));
        if (!removed){
            return AjaxResult.error("删除失败");
        }
        for (String id : ids){
            List<KingAllocateDetailEntity> list = kingAllocateDetailService.list(new LambdaQueryWrapper<KingAllocateDetailEntity>().eq(KingAllocateDetailEntity::getAllocateId, id));
            if (!CollectionUtils.isEmpty(list)){
                List<String> resultIds = list.stream().map(kingAllocateDetailEntity -> kingAllocateDetailEntity.getId()).collect(Collectors.toList());
                boolean removeByIds = kingAllocateDetailService.removeByIds(resultIds);
                if (!removeByIds){
                    return AjaxResult.error("删除失败");
                }
            }
        }
        return AjaxResult.success("删除成功");
    }

    /**
     * 删除调拨申请单信息
     *
     * @param id 调拨申请单ID
     * @return 结果
     */
    @Override
    public int deleteKingApplyAllocateById(String id) {
        return kingApplyAllocateMapper.deleteKingApplyAllocateById(id);
    }

    /**
     * 分页查询调拨申请单
     * @param kingApplyAllocateDto
     * @return
     */
    @Override
    public IPage<KingApplyAllocateVo> selectKingApplyAllocateListPage(KingApplyAllocateDto kingApplyAllocateDto) {
        return kingApplyAllocateMapper.selectKingApplyAllocateListPage(kingApplyAllocateDto);
    }

    /**
     * 校验库存
     *
     * @param kingAllocateDetailEntityList
     */
    private void checkKingRealInventory(List<KingAllocateDetailEntity> kingAllocateDetailEntityList) {
        for (KingAllocateDetailEntity kingAllocateDetailEntity : kingAllocateDetailEntityList) {
            KingRealInventoryEntity realInventoryEntity = kingRealInventoryEntityService.getOne(new LambdaQueryWrapper<KingRealInventoryEntity>()
                    .eq(KingRealInventoryEntity::getWarehouseCode, kingAllocateDetailEntity.getOutWarehouse())
                    .eq(KingRealInventoryEntity::getWarehousePosition, kingAllocateDetailEntity.getOutWarehouseRegion())
                    .eq(KingRealInventoryEntity::getMaterialCode, kingAllocateDetailEntity.getMaterialCode()));
            if (Objects.isNull(realInventoryEntity)) {
                throw new RuntimeException("没有此库存");
            }
            List<KingAllocateDetailEntity> collect = kingAllocateDetailEntityList.stream().filter(s ->
                    s.getMaterialCode().equals(kingAllocateDetailEntity.getMaterialCode()) &&
                            s.getOutWarehouse().equals(kingAllocateDetailEntity.getOutWarehouse()) &&
                            s.getOutWarehouseRegion().equals(kingAllocateDetailEntity.getOutWarehouseRegion())

            ).collect(Collectors.toList());
            BigDecimal sum = collect.stream().map(KingAllocateDetailEntity::getAllocateNum).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (sum.compareTo(new BigDecimal(realInventoryEntity.getInventoryNum())) > 0) {
                throw new RuntimeException("库存不足");
            }
        }
    }
}
